package ar.edu.utn.frsf.proyectofinal.sistemadecontrolmodbus.devicecontroller.imp;

import java.io.IOException;

import ar.edu.utn.frsf.proyectofinal.sistemadecontrolmodbus.persistence.DeviceDAO;
import ar.edu.utn.frsf.proyectofinal.sistemadecontrolmodbus.persistence.model.Device;
import ar.edu.utn.frsf.proyectofinal.sistemadecontrolmodbus.devicecontroller.DeviceManager;
import ar.edu.utn.frsf.proyectofinal.sistemadecontrolmodbus.devicecontroller.factories.DeviceManagerFactory;

import net.wimpi.modbus.ModbusIOException;
import net.wimpi.modbus.io.ModbusTransport;
import net.wimpi.modbus.msg.ModbusResponse;
import net.wimpi.modbus.msg.ReadInputRegistersRequest;
import net.wimpi.modbus.msg.ReadInputRegistersResponse;
import net.wimpi.modbus.msg.WriteSingleRegisterRequest;
import net.wimpi.modbus.procimg.SimpleRegister;

public class AutomaticConnectionHandler implements Runnable{

	private ModbusTransport incoming;
	private DeviceManagerFactory deviceManagerFactory;
	private DeviceDAO deviceDAO;
	private ModbusResponse res;
	
	@Override
	public void run() {
		try {
			authenticate();
			incoming.close();
		} catch (ModbusIOException e) {
		} catch (IOException e) {
		}
		
	}
	public void authenticate() throws ModbusIOException{
			DeviceManager deviceManager = null;
			res = requestDeviceID();
			if(res instanceof ReadInputRegistersResponse){
				if(((ReadInputRegistersResponse)res).getByteCount() == 1){
					int deviceNbr = ((ReadInputRegistersResponse)res).getRegisterValue(0);
					//TODO: check race condition. what happens if two connection to same device
					//if(devman.canAutoConnect(deviceNbr,incoming))success = true;
					Device dev = deviceDAO.findDevice(Integer.valueOf(deviceNbr));
					if(dev != null){
						if(dev.getAutoConection()){
							deviceManager = deviceManagerFactory.create(dev);
							//It is waiting for a connection (not connected yet)
							deviceManager.initAutomaticConnection(incoming,this);
							return;
						}
					}
					sendFail();
				}
			}
		
	}
	
	public void sendFail() throws ModbusIOException {
		WriteSingleRegisterRequest req = createConfirmationRequest();
		req.setRegister(new SimpleRegister(0));
		incoming.writeMessage(req);
		incoming.readResponse();
		
	}

	public void sendConfirmation() throws ModbusIOException {
		WriteSingleRegisterRequest req = createConfirmationRequest();
		req.setRegister(new SimpleRegister(1));
		incoming.writeMessage(req);
		incoming.readResponse();
		
	}
	
	private WriteSingleRegisterRequest createConfirmationRequest() {
		WriteSingleRegisterRequest req = new WriteSingleRegisterRequest(); 
		req.setTransactionID(1);
		req.setReference(0);
		req.setUnitID(res.getUnitID());
		return req;
	}
	private ModbusResponse requestDeviceID() throws ModbusIOException {
		ReadInputRegistersRequest req1 = new ReadInputRegistersRequest(); 
		req1.setTransactionID(0);
		req1.setReference(0);
		req1.setWordCount(1);
		incoming.writeMessage(req1);
		return incoming.readResponse();
	}
	/**
	 * @return the incoming
	 */
	public ModbusTransport getIncoming() {
		return incoming;
	}
	/**
	 * @param incoming the incoming to set
	 */
	public void setIncoming(ModbusTransport incoming) {
		this.incoming = incoming;
	}


	/**
	 * @return the deviceManagerFactory
	 */
	public DeviceManagerFactory getDeviceManagerFactory() {
		return deviceManagerFactory;
	}
	/**
	 * @param deviceManagerFactory the deviceManagerFactory to set
	 */
	public void setDeviceManagerFactory(DeviceManagerFactory deviceManagerFactory) {
		this.deviceManagerFactory = deviceManagerFactory;
	}
	/**
	 * @return the deviceDAO
	 */
	public DeviceDAO getDeviceDAO() {
		return deviceDAO;
	}
	/**
	 * @param deviceDAO the deviceDAO to set
	 */
	public void setDeviceDAO(DeviceDAO deviceDAO) {
		this.deviceDAO = deviceDAO;
	}

	
}
